package com.l2jserver.gameserver.communitybbs.Manager;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.logging.Level;

import javolution.text.TextBuilder;

import com.l2jserver.Config;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.cache.HtmCache;
import com.l2jserver.gameserver.communitybbs.BB.TopPost;
import com.l2jserver.gameserver.communitybbs.Model.BaseBBSManager;
import com.l2jserver.gameserver.datatables.ClanTable;
import com.l2jserver.gameserver.datatables.ImagesTables;
import com.l2jserver.gameserver.datatables.NpcTable;
import com.l2jserver.gameserver.instancemanager.CastleManager;
import com.l2jserver.gameserver.instancemanager.GrandBossManager;
import com.l2jserver.gameserver.instancemanager.RaidBossSpawnManager;
import com.l2jserver.gameserver.instancemanager.RaidBossSpawnManager.StatusEnum;
import com.l2jserver.gameserver.model.L2Clan;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.StatsSet;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.Castle;
import com.l2jserver.gameserver.model.entity.Hero;
import com.l2jserver.gameserver.model.itemcontainer.PcInventory;
import com.l2jserver.gameserver.model.olympiad.Olympiad;
import com.l2jserver.gameserver.network.serverpackets.ShowBoard;
import com.l2jserver.gameserver.util.audit.CommunityAudit;

/**
 * @author st0rm
 * @reworked fissban
 */
public class HomeBBSManager extends BaseBBSManager
{
	// Aux de clase
	private Map<Integer, String> classList;
	// paginas de comunidad
	private final Map<String, TopPost> _boardsMenu = new TreeMap<>();
	// Variables para hero
	private final List<TopPost> _heroList = new ArrayList<>();
	private int olympiad_cycle = -1;
	// Variables para gb
	private TopPost _grandBoss = null;
	// Variables para castillos
	private TopPost _castle = null;
	// Variables para Top Adena/Pk/Pvp/clan
	private TopPost _topAdena = null;
	private TopPost _topPk = null;
	private TopPost _topPvp = null;
	private TopPost _topClan = null;
	// Variables para rb
	private final Map<Integer, ArrayList<TopPost>> _raidList = new TreeMap<>();
	// Variable para las noticias
	private TopPost _infoNews = null;
	// Variable para la informacion general del servidor
	private TopPost _infoGral = null;
	private TopPost _infoRate = null;
	private TopPost _infoOther = null;
	private TopPost _infoRules = null;
	
	@Override
	public void parseCmd(String command, L2PcInstance activeChar)
	{
		ImagesTables.getInstance().sendImage(activeChar, 8001);
		ImagesTables.getInstance().sendImage(activeChar, 8002);
		ImagesTables.getInstance().sendImage(activeChar, 8003);
		ImagesTables.getInstance().sendImage(activeChar, 8004);
		
		if (command.equals("_bbshome"))
		{
			String content = HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/CommunityBoard/custom/home/index.htm");
			if (content == null)
			{
				content = "<html><body><br><br><center>404 :File not found: 'data/html/CommunityBoard/custom/home/index.htm' </center></body></html>";
			}
			separateAndSend(content, activeChar);
		}
		else if (command.startsWith("_bbshome;"))
		{
			StringTokenizer st = new StringTokenizer(command, ";");
			st.nextToken();// _bbshome
			String idp = st.nextToken();
			String content = HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/CommunityBoard/custom/home/" + idp + ".htm");
			if (content == null)
			{
				content = "<html><body><br><br><center>The command " + command + " points to file(" + idp + ".htm) that NOT exists.</center></body></html>";
				separateAndSend(content, activeChar);
				return;
			}
			
			if (content.isEmpty())
			{
				content = "<html><body><br><br><center>Content Empty: The command " + command + " points to an invalid or empty html file(" + idp + ".htm).</center></body></html>";
			}
			if (idp.equals("donation"))
			{
				//
			}
			else if (idp.equals("staff"))
			{
				//
			}
			else if (idp.equals("infogral"))
			{
				content = content.replaceAll("%current_header%", getInfo().getHeader());
				if (st.hasMoreTokens())
				{
					String type = st.nextToken();
					if (type.toLowerCase().equals("rate"))
					{
						content = content.replaceAll("%current_body%", getInfoRate().getBody());
						content = content.replaceAll("%current_footer%", getInfoRate().getFooter());
					}
					else if (type.toLowerCase().equals("other"))
					{
						content = content.replaceAll("%current_body%", getInfoOther().getBody());
						content = content.replaceAll("%current_footer%", getInfoOther().getFooter());
					}
					else if (type.toLowerCase().equals("rules"))
					{
						content = content.replaceAll("%current_body%", getInfoRules().getBody());
						content = content.replaceAll("%current_footer%", getInfoRules().getFooter());
					}
					else if (type.toLowerCase().equals("news"))
					{
						content = content.replaceAll("%current_body%", getInfoNew().getBody());
						content = content.replaceAll("%current_footer%", getInfoNew().getFooter());
					}
				}
				else
				{
					content = content.replaceAll("%current_body%", "");
					content = content.replaceAll("%current_footer%", "");
				}
			}
			else if (idp.equals("topindex"))
			{
				content = content.replaceAll("%menu%", getBoardHeader(idp));
				if (st.hasMoreTokens())
				{
					String type = st.nextToken();
					if (type.toLowerCase().equals("clan"))
					{
						if (!Config.TOP_ALLOW_CLANRANK)
						{
							CommunityAudit.auditCommunity("Player: " + activeChar.getName() + " utiliza la opcion " + type + " estando desactivada.");
							return;
						}
						
						content = content.replaceAll("%current_header%", getClanRank().getHeader());
						content = content.replaceAll("%current_body%", getClanRank().getBody());
						content = content.replaceAll("%current_footer%", getClanRank().getFooter());
					}
					else if (type.toLowerCase().equals("adena"))
					{
						if (!Config.TOP_ALLOW_ADENARANK)
						{
							CommunityAudit.auditCommunity("Player: " + activeChar.getName() + " utiliza la opcion " + type + " estando desactivada.");
							return;
						}
						
						content = content.replaceAll("%current_header%", getAdenaRank().getHeader());
						content = content.replaceAll("%current_body%", getAdenaRank().getBody());
						content = content.replaceAll("%current_footer%", getAdenaRank().getFooter());
					}
					else if (type.toLowerCase().equals("pvp"))
					{
						if (!Config.TOP_ALLOW_PVPRANK)
						{
							CommunityAudit.auditCommunity("Player: " + activeChar.getName() + " utiliza la opcion " + type + " estando desactivada.");
							return;
						}
						
						content = content.replaceAll("%current_header%", getPvpRank().getHeader());
						content = content.replaceAll("%current_body%", getPvpRank().getBody());
						content = content.replaceAll("%current_footer%", getPvpRank().getFooter());
					}
					else if (type.toLowerCase().equals("pk"))
					{
						if (!Config.TOP_ALLOW_PKRANK)
						{
							CommunityAudit.auditCommunity("Player: " + activeChar.getName() + " utiliza la opcion " + type + " estando desactivada.");
							return;
						}
						
						content = content.replaceAll("%current_header%", getPkRank().getHeader());
						content = content.replaceAll("%current_body%", getPkRank().getBody());
						content = content.replaceAll("%current_footer%", getPkRank().getFooter());
					}
					else
					{
						content = content.replaceAll("%current_header%", "");
						content = content.replaceAll("%current_body%", "");
						content = content.replaceAll("%current_footer%", "");
					}
				}
				else
				{
					content = content.replaceAll("%current_header%", "");
					content = content.replaceAll("%current_body%", "");
					content = content.replaceAll("%current_footer%", "");
				}
			}
			else if (idp.equals("infoindex"))
			{
				content = content.replaceAll("%menu%", getBoardHeader(idp));
				
				if (st.hasMoreTokens())
				{
					String type = st.nextToken();
					if (type.toLowerCase().equals("hero"))
					{
						if (!Config.TOP_ALLOW_HEROINFO)
						{
							CommunityAudit.auditCommunity("Player: " + activeChar.getName() + " utiliza la opcion " + type + " estando desactivada.");
							return;
						}
						
						if (st.hasMoreTokens())
						{
							int slot = Integer.parseInt(st.nextToken());
							content = content.replaceAll("%raid_level%", "");
							content = content.replaceAll("%current_header%", getHero(slot).getHeader());
							content = content.replaceAll("%current_body%", getHero(slot).getBody());
							content = content.replaceAll("%current_footer%", getHero(slot).getFooter());
						}
						else
						{
							content = content.replaceAll("%raid_level%", "");
							content = content.replaceAll("%current_header%", getHero(0).getHeader());
							content = content.replaceAll("%current_body%", getHero(0).getBody());
							content = content.replaceAll("%current_footer%", getHero(0).getFooter());
						}
					}
					else if (type.toLowerCase().equals("raid"))
					{
						if (!Config.TOP_ALLOW_RAIDINFO)
						{
							CommunityAudit.auditCommunity("Player: " + activeChar.getName() + " utiliza la opcion " + type + " estando desactivada.");
							return;
						}
						
						content = content.replaceAll("%raid_level%", getBoardHeader("raid_level"));
						
						if (st.hasMoreTokens())
						{
							int ran = Integer.parseInt(st.nextToken());
							
							if (st.hasMoreTokens())
							{
								int slot = Integer.parseInt(st.nextToken());
								content = content.replaceAll("%current_header%", getRaid(ran, slot).getHeader());
								content = content.replaceAll("%current_body%", getRaid(ran, slot).getBody());
								content = content.replaceAll("%current_footer%", getRaid(ran, slot).getFooter());
							}
							else
							{
								content = content.replaceAll("%current_header%", getRaid(ran, 0).getHeader());
								content = content.replaceAll("%current_body%", getRaid(ran, 0).getBody());
								content = content.replaceAll("%current_footer%", getRaid(ran, 0).getFooter());
							}
						}
						else
						{
							content = content.replaceAll("%current_header%", "");
							content = content.replaceAll("%current_body%", "");
							content = content.replaceAll("%current_footer%", "");
						}
					}
					else if (type.toLowerCase().equals("grand"))
					{
						if (!Config.TOP_ALLOW_GRANDBOSSINFO)
						{
							CommunityAudit.auditCommunity("Player: " + activeChar.getName() + " utiliza la opcion " + type + " estando desactivada.");
							return;
						}
						
						content = content.replaceAll("%raid_level%", "");
						content = content.replaceAll("%current_header%", getGrandBoss().getHeader());
						content = content.replaceAll("%current_body%", getGrandBoss().getBody());
						content = content.replaceAll("%current_footer%", getGrandBoss().getFooter());
					}
					else if (type.toLowerCase().equals("castle"))
					{
						if (!Config.TOP_ALLOW_CASTLEINFO)
						{
							CommunityAudit.auditCommunity("Player: " + activeChar.getName() + " utiliza la opcion " + type + " estando desactivada.");
							return;
						}
						
						content = content.replaceAll("%raid_level%", "");
						content = content.replaceAll("%current_header%", getCastle().getHeader());
						content = content.replaceAll("%current_body%", getCastle().getBody());
						content = content.replaceAll("%current_footer%", getCastle().getFooter());
					}
					else
					{
						content = content.replaceAll("%raid_level%", "");
						content = content.replaceAll("%current_header%", "");
						content = content.replaceAll("%current_body%", "");
						content = content.replaceAll("%current_footer%", "");
					}
				}
				else
				{
					content = content.replaceAll("%raid_level%", "");
					content = content.replaceAll("%current_header%", "");
					content = content.replaceAll("%current_body%", "");
					content = content.replaceAll("%current_footer%", "");
				}
			}
			
			separateAndSend(content, activeChar);
		}
		else
		{
			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command + " is not implemented yet</center><br><br></body></html>", "101");
			activeChar.sendPacket(sb);
			activeChar.sendPacket(new ShowBoard(null, "102"));
			activeChar.sendPacket(new ShowBoard(null, "103"));
		}
	}
	
	@Override
	public void parseWrite(String ar1, String ar2, String ar3, String ar4, String ar5, L2PcInstance activeChar)
	{
		//
	}
	
	private void generateInfoGralIndex()
	{
		// Genero el Header
		TextBuilder _header = new TextBuilder();
		_header.append("<br>");
		_header.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=755>");
		_header.append("<tr>");
		_header.append("<td FIXWIDTH=755 align=center valign=top><font name=hs12>LINEAGE II</font></td>");
		_header.append("</tr>");
		_header.append("</table>");
		_header.append("<br>");
		_header.append("<br>");
		// _header.append("<img src=L2UI.squaregray WIDTH=755 height=1>");
		_header.append("<table border=0 cellspacing=0 cellpadding=2 WIDTH=755 bgcolor=111111 height=40>");
		_header.append("<tr>");
		_header.append("<td FIXWIDTH=100 align=right><img src=L2UI.bbs_folder WIDTH=32 height=32></td>");
		_header.append("<td FIXWIDTH=480 align=left><font color=E95600>Server Information</font><br1><font color=AAAAAA>Here are all the server data.</font></td>");
		_header.append("<td FIXWIDTH=160 align=center><button value=\"\" action=\"bypass _bbshome\" back=L2UI_CT1.MiniMap_DF_MinusBtn_Red fore=L2UI_CT1.MiniMap_DF_MinusBtn_Red WIDTH=32 height=32/></td>");
		_header.append("</tr>");
		_header.append("</table>");
		// _header.append("<img src=L2UI.squaregray WIDTH=755 height=1>");
		_header.append("<br>");
		_header.append("<table border=0 cellspacing=0 cellpadding=2 height=50>");
		_header.append("<tr>");
		_header.append("<td><button action=\"bypass _bbshome;infogral;news\" value=\"News\" WIDTH=150 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
		_header.append("<td><button action=\"bypass _bbshome;infogral;rules\" value=\"Rules\" WIDTH=150 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
		_header.append("<td><button action=\"bypass _bbshome;infogral;rate\" value=\"Rates\" WIDTH=150 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
		_header.append("<td><button action=\"bypass _bbshome;infogral;other\" value=\"Other\" WIDTH=150 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
		_header.append("</tr>");
		_header.append("</table>");
		_infoGral = new TopPost(_header.toString(), "", "");
	}
	
	private void generateRate()
	{
		// Genero el body
		TextBuilder _body = new TextBuilder();
		_body.append("<br>");
		int pos = 1;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>XP Rate:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.RATE_XP + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// exp party
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Party XP Rate:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.RATE_PARTY_XP + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// exp vip
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>XP Rate Vip:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + (Config.RATE_XP * Config.RATE_XP_VIP) + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// sp
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Sp Rate:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.RATE_SP + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// exp party
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Party SP Rate:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.RATE_PARTY_SP + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// sp vip
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>SP Rate Vip:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + (Config.RATE_SP * Config.RATE_SP_VIP) + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// Exp mascotas
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>XP Rate Pet:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.PET_XP_RATE + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// drop items
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Drop Rate:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.RATE_DROP_ITEMS + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// drop items Vip
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Drop Rate Vip:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.RATE_DROP_ITEMS_VIP + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// drop items Adena
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Adena Rate:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.RATE_DROP_ITEMS_ID.get(PcInventory.ADENA_ID) + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// drop items Adena Vip
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Adena Rate:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.RATE_DROP_ITEMS_ID_VIP.get(PcInventory.ADENA_ID) + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// Drop Spoil
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Spoil Rate:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.RATE_DROP_SPOIL + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// Drop Spoil Vip
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Spoil Rate Vip:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.RATE_DROP_SPOIL_VIP + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// Drop Quest
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Quest Rate:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.RATE_QUEST_DROP + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// Drop Quest Reward
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Quest Rate Reward:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.RATE_QUEST_REWARD + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		_infoRate = new TopPost("", _body.toString(), "");
	}
	
	private void generateOtherConfig()
	{
		// Genero el body
		TextBuilder _body = new TextBuilder();
		_body.append("<br>");
		int pos = 0;
		
		// Max Buff
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Max Buff Amount:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.BUFFS_MAX_AMOUNT + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// Max Dance & Song
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Max Dance & Song:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.DANCES_MAX_AMOUNT + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// Max casting speed
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Max Casting Speed:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.MAX_MATK_SPEED + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// Max casting speed
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Max Attack Speed:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.MAX_PATK_SPEED + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// critical rate P
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Max Patk Critcal Rate:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.MAX_PCRIT_RATE + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// critical rate M
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Max Matk Critcal Rate:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.MAX_MCRIT_RATE + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// Run speed
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Max Run Speed:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.MAX_RUN_SPEED + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		// Max Evasion
		pos++;
		_body.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=300 bgcolor=" + getColor(pos) + ">");
		_body.append("<tr>");
		_body.append("<td FIXWIDTH=250 HEIGHT=20 align=center valign=top>Max Evasion:</td>");
		_body.append("<td FIXWIDTH=50 HEIGHT=20 align=center valign=top><font color=99FF00>" + Config.MAX_EVASION + "</font></td>");
		_body.append("</tr>");
		_body.append("</table>");
		
		_infoOther = new TopPost("", _body.toString(), "");
	}
	
	private void generateInfoRules()
	{
		// Genero el body
		final File file = new File(Config.DATAPACK_ROOT, "data/html/CommunityBoard/custom/home/rules.txt");
		TextBuilder _body = new TextBuilder();
		try (FileReader fr = new FileReader(file);
			LineNumberReader lnr = new LineNumberReader(fr))
		{
			String line = null;
			int position = 1;
			while ((line = lnr.readLine()) != null)
			{
				_body.append("<table border=0 cellspacing=0 cellpadding=2 WIDTH=755 height=25 bgcolor=" + getColor(position) + ">");
				_body.append("<tr><td FIXWIDTH=755 align=center>");
				
				StringTokenizer st = new StringTokenizer(line, Config.EOL);
				if (st.hasMoreTokens())
				{
					_body.append(position + "-  " + st.nextToken());
				}
				position++;
				_body.append("</td></tr>");
				_body.append("</table>");
			}
		}
		catch (IOException e1)
		{
			_log.log(Level.SEVERE, "Error reading news.txt: ", e1);
		}
		
		_infoRules = new TopPost("", _body.toString(), "");
	}
	
	private void generateInfoNews()
	{
		// Genero el body
		final File file = new File(Config.DATAPACK_ROOT, "data/html/CommunityBoard/custom/home/news.txt");
		TextBuilder _body = new TextBuilder();
		try (FileReader fr = new FileReader(file);
			LineNumberReader lnr = new LineNumberReader(fr))
		{
			String line = null;
			int position = 1;
			while ((line = lnr.readLine()) != null)
			{
				_body.append("<table border=0 cellspacing=0 cellpadding=2 WIDTH=755 height=25 bgcolor=" + getColor(position) + ">");
				_body.append("<tr><td FIXWIDTH=755 align=center>");
				
				StringTokenizer st = new StringTokenizer(line, Config.EOL);
				if (st.hasMoreTokens())
				{
					_body.append(st.nextToken());
				}
				position++;
				_body.append("</td></tr>");
				_body.append("</table>");
			}
		}
		catch (IOException e1)
		{
			_log.log(Level.SEVERE, "Error reading news.txt: ", e1);
		}
		
		_infoNews = new TopPost("", _body.toString(), "");
	}
	
	private void generateHeroPage()
	{
		if (Config.TOP_ALLOW_HEROINFO)
		{
			// Genero el Header para los heroes
			TextBuilder _header = new TextBuilder();
			_header.append("<table border=0 cellspacing=0 cellpadding=2 FIXWIDTH=650 bgcolor=D2D2D2>");
			_header.append("<tr><td FIXWIDTH=40 align=center>#</td><td FIXWIDTH=150 align=center>Name</td><td FIXWIDTH=100 align=center>Class</td><td FIXWIDTH=80 align=center>Ammount</td><td FIXWIDTH=140 align=center>Clan</td><td FIXWIDTH=140 align=center>Alliance</td></tr>");
			_header.append("</table>");
			
			Map<Integer, StatsSet> heroList = Hero.getInstance().getHeroes();
			int heroCount = heroList.size();
			int heroPages = (int) Math.ceil(heroCount / 15.);
			
			if (heroList.size() != 0)
			{
				// Genero el Footer para los heroes
				TextBuilder _footer = new TextBuilder();
				_footer.append("<table border=0 cellspacing=0 cellpadding=2 height=50>");
				_footer.append("<tr>");
				
				for (int i = 0; i < heroPages; i++)
				{
					_footer.append("<td><button action=\"bypass _bbshome;infoindex;Hero;" + i + "\" value=" + (i + 1) + " FIXWIDTH=50 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
				}
				_footer.append("</tr>");
				_footer.append("</table>");
				
				int position = 1;
				int index = 0;
				int pageWrite = 0;
				TextBuilder _body = new TextBuilder();
				
				for (Integer heroId : heroList.keySet())
				{
					if (index == 15)
					{
						index = 0;
						TopPost tp = new TopPost(_header.toString(), _body.toString(), _footer.toString());
						_heroList.add(tp);
						pageWrite++;
					}
					
					if (index == 0)
					{
						_body = new TextBuilder();
					}
					
					StatsSet ss = heroList.get(heroId);
					
					// Genero el Body
					_body.append("<table border=0 cellspacing=0 cellpadding=2 FIXWIDTH=650 bgcolor=" + getColor(position) + ">");
					_body.append("<tr>");
					_body.append("<td FIXWIDTH=40 align=center>" + position + "</td>");
					_body.append("<td FIXWIDTH=150 align=center>" + ss.getString(Olympiad.CHAR_NAME) + "</td>");
					_body.append("<td FIXWIDTH=100 align=center>" + getClassName(ss.getInteger(Olympiad.CLASS_ID)) + "</td>");
					_body.append("<td FIXWIDTH=80 align=center>" + ss.getInteger(Hero.COUNT) + "</td>");
					_body.append("<td FIXWIDTH=140 align=center>" + ss.getString(Hero.CLAN_NAME, "") + "</td>");
					_body.append("<td FIXWIDTH=140 align=center>" + ss.getString(Hero.ALLY_NAME, "") + "</td>");
					_body.append("</tr>");
					_body.append("</table>");
					index++;
					position++;
					
					if (pageWrite < heroPages)
					{
						TopPost tp = new TopPost(_header.toString(), _body.toString(), _footer.toString());
						_heroList.add(tp);
					}
				}
			}
			else
			{
				TopPost tp = new TopPost(_header.toString(), "", "");
				_heroList.add(tp);
			}
		}
	}
	
	private void generateGrandBossList()
	{
		if (Config.TOP_ALLOW_GRANDBOSSINFO)
		{
			// Genero el header
			TextBuilder _header = new TextBuilder();
			_header.append("<table border=0 cellspacing=0 cellpadding=2 bgcolor=D2D2D2>");
			_header.append("<tr><td FIXWIDTH=130 align=center>Nombre</td><td FIXWIDTH=60 align=center>Estado</td></tr>");
			_header.append("</table>");
			
			// Genero el body
			TextBuilder _body = new TextBuilder();
			int position = 1;
			
			for (int i : Config.TOP_GRANDBOSS_LIST)
			{
				String name = NpcTable.getInstance().getTemplate(i).getName();
				int status = GrandBossManager.getInstance().getBossStatus(i);
				_body.append("<table border=0 cellspacing=0 cellpadding=2 bgcolor=" + getColor(position) + ">");
				_body.append("<tr>");
				_body.append("<td FIXWIDTH=130 align=center>" + name + "</td>");
				_body.append("<td FIXWIDTH=60 align=center>" + ((status == 0) ? "<font color=99FF00>Alive</font>" : "<font color=CC0000>Dead</font>") + "</td>");
				_body.append("</tr>");
				_body.append("</table>");
				position++;
			}
			_grandBoss = new TopPost(_header.toString(), _body.toString(), "");
		}
	}
	
	private void generateRaidList()
	{
		if (Config.TOP_ALLOW_RAIDINFO)
		{
			int[] range = new int[]
			{
				20,
				30,
				40,
				50,
				60,
				70,
				80
			};
			
			// Genero el header
			TextBuilder _header = new TextBuilder();
			_header.append("<table border=0 cellspacing=0 cellpadding=2 FIXWIDTH=270 bgcolor=D2D2D2>");
			_header.append("<tr><td FIXWIDTH=170 align=center>Name</td><td FIXWIDTH=50 align=center>Level</td><td FIXWIDTH=50 align=center>State</td></tr>");
			_header.append("</table>");
			
			for (int i : range)
			{
				int index = 0;
				int position = 1;
				int pageWrite = 0;
				ArrayList<TopPost> tpl = new ArrayList<>();
				TextBuilder _body = new TextBuilder();
				for (L2Spawn sp : RaidBossSpawnManager.getInstance().getSpawns().values())
				{
					if ((sp.getTemplate().getLevel() >= i) && (sp.getTemplate().getLevel() < (i + 10)))
					{
						if (index == 15)
						{
							index = 0;
							TopPost tp = new TopPost(_header.toString(), _body.toString(), "");
							tpl.add(tp);
							pageWrite++;
						}
						
						if (index == 0)
						{
							_body = new TextBuilder();
						}
						
						_body.append("<table border=0 cellspacing=0 cellpadding=2 FIXWIDTH=270 bgcolor=" + getColor(position) + ">");
						_body.append("<tr>");
						_body.append("<td FIXWIDTH=170 align=center>" + sp.getTemplate().getName() + "</td>");
						_body.append("<td FIXWIDTH=50 align=center>" + sp.getTemplate().getLevel() + "</td>");
						_body.append("<td FIXWIDTH=50 align=center>" + ((RaidBossSpawnManager.getInstance().getRaidBossStatusId(sp.getNpcid()) == StatusEnum.ALIVE) ? "<font color=99FF00>Alive</font>" : "<font color=CC0000>Dead</font>") + "</td>");
						_body.append("</tr>");
						_body.append("</table>");
						position++;
						index++;
					}
				}
				int PageCount = (int) Math.ceil((position - 1) / 15.);
				
				if (pageWrite < PageCount)
				{
					TopPost tp = new TopPost(_header.toString(), _body.toString(), "");
					tpl.add(tp);
				}
				
				// Genero el footer
				TextBuilder _footer = new TextBuilder();
				_footer.append("<table border=0 cellspacing=0 cellpadding=2 height=50>");
				_footer.append("<tr>");
				
				for (int j = 0; j < PageCount; j++)
				{
					_footer.append("<td><button action=\"bypass _bbshome;infoindex;Raid;" + i + ";" + j + "\" value=" + (j + 1) + " WIDTH=50 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
				}
				
				_footer.append("</tr>");
				_footer.append("</table>");
				
				for (TopPost t : tpl)
				{
					t.setFooter(_footer.toString());
				}
				_raidList.put(i, tpl);
			}
		}
	}
	
	private void generateCastlePage()
	{
		// Genero header
		TextBuilder _header = new TextBuilder();
		_header.append("<table border=0 cellspacing=0 cellpadding=2 FIXWIDTH=420 bgcolor=D2D2D2>");
		_header.append("<tr>");
		_header.append("<td FIXWIDTH=100 align=center>Nombre</td>");
		_header.append("<td FIXWIDTH=100 align=center>Dueño</td>");
		_header.append("<td FIXWIDTH=40 align=center>Tax</td>");
		_header.append("<td FIXWIDTH=180 align=center>Asedio</td>");
		_header.append("</tr>");
		_header.append("</table>");
		
		// Genero el body
		TextBuilder _body = new TextBuilder();
		int position = 1;
		for (Castle c : CastleManager.getInstance().getCastles())
		{
			String owner_name;
			if (c.getOwnerId() == 0)
			{
				owner_name = "NPC Clan";
			}
			else
			{
				L2Clan clan = ClanTable.getInstance().getClan(c.getOwnerId());
				owner_name = clan.getName();
			}
			
			Date siegeDate = new Date(c.getSiegeDate().getTimeInMillis());
			String DATE_FORMAT = "dd-MMM-yyyy HH:mm";
			SimpleDateFormat sformat = new SimpleDateFormat(DATE_FORMAT);
			
			_body.append("<table border=0 cellspacing=0 cellpadding=2 FIXWIDTH=420 bgcolor=" + getColor(position) + ">");
			_body.append("<tr>");
			_body.append("<td FIXWIDTH=100 align=center>" + c.getName() + "</td>");
			_body.append("<td FIXWIDTH=100 align=center>" + owner_name + "</td>");
			_body.append("<td FIXWIDTH=40 align=center>" + c.getTaxPercent() + "%</td>");
			_body.append("<td FIXWIDTH=180 align=center>" + sformat.format(siegeDate) + "</td>");
			_body.append("</tr>");
			_body.append("</table>");
			position++;
		}
		_castle = new TopPost(_header.toString(), _body.toString(), "");
	}
	
	private void generateTopAdena()
	{
		if (!Config.TOP_ALLOW_ADENARANK)
		{
			return;
		}
		
		// Genero el header
		TextBuilder _header = new TextBuilder();
		_header.append("<table border=0 cellspacing=0 cellpadding=2 FIXWIDTH=550 bgcolor=D2D2D2>");
		_header.append("<tr><td FIXWIDTH=50 align=center>#</td><td FIXWIDTH=200 align=center>Name</td><td FIXWIDTH=100 align=center>Class</td><td FIXWIDTH=200 align=center>Adena</td></tr>");
		_header.append("</table>");
		
		// Genero el body
		TextBuilder _body = new TextBuilder();
		
		try (Connection con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement statement = con.prepareStatement("SELECT SUM(it.count) val, ch.char_name name, ch.base_class base FROM characters ch, items it WHERE ch.accesslevel = 0 AND it.item_id = 57 AND it.owner_id = ch.charId GROUP BY ch.charId ORDER BY SUM(it.count) DESC LIMIT " + Config.TOP_PLAYER_RESULTS))
		{
			int position = 1;
			try (ResultSet result = statement.executeQuery())
			{
				while (result.next())
				{
					
					_body.append("<table border=0 cellspacing=0 cellpadding=2 FIXWIDTH=550 bgcolor=" + getColor(position) + ">");
					_body.append("<tr>");
					_body.append("<td FIXWIDTH=50 align=center>" + position + "</td>");
					_body.append("<td FIXWIDTH=200 align=center>" + result.getString("name") + "</td>");
					_body.append("<td FIXWIDTH=100 align=center>" + getClassName(result.getInt("base")) + "</td>");
					_body.append("<td FIXWIDTH=200 align=center>" + result.getLong("val") + "</td>");
					_body.append("</tr></table>");
					position++;
				}
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		_topAdena = new TopPost(_header.toString(), _body.toString(), "");
	}
	
	private void generateTopPvp()
	{
		if (!Config.TOP_ALLOW_PVPRANK)
		{
			return;
		}
		// Genero el header
		TextBuilder _header = new TextBuilder();
		_header.append("<table border=0 cellspacing=0 cellpadding=2 FIXWIDTH=550 bgcolor=D2D2D2>");
		_header.append("<tr><td FIXWIDTH=50 align=center>#</td><td FIXWIDTH=200 align=center>Name</td><td FIXWIDTH=100 align=center>Class</td><td FIXWIDTH=200 align=center>PvP</td></tr>");
		_header.append("</table>");
		
		// Genero el body
		TextBuilder _body = new TextBuilder();
		
		try (Connection con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement statement = con.prepareStatement("SELECT char_name name , pvpkills val, base_class base FROM characters WHERE accesslevel = 0 AND pvpkills > 0  ORDER BY pvpkills DESC LIMIT " + Config.TOP_PLAYER_RESULTS))
		{
			int position = 1;
			try (ResultSet result = statement.executeQuery())
			{
				while (result.next())
				{
					_body.append("<table border=0 cellspacing=0 cellpadding=2 FIXWIDTH=550 bgcolor=" + getColor(position) + ">");
					_body.append("<tr>");
					_body.append("<td FIXWIDTH=50 align=center>" + position + "</td>");
					_body.append("<td FIXWIDTH=200 align=center>" + result.getString("name") + "</td>");
					_body.append("<td FIXWIDTH=100 align=center>" + getClassName(result.getInt("base")) + "</td>");
					_body.append("<td FIXWIDTH=200 align=center>" + result.getInt("val") + "</td>");
					_body.append("</tr></table>");
					position++;
				}
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		_topPvp = new TopPost(_header.toString(), _body.toString(), "");
	}
	
	private void generateTopClan()
	{
		if (!Config.TOP_ALLOW_CLANRANK)
		{
			return;
		}
		// Genero el header
		TextBuilder _header = new TextBuilder();
		_header.append("<table border=0 cellspacing=0 cellpadding=2 FIXWIDTH=540 bgcolor=D2D2D2>");
		_header.append("<tr><td FIXWIDTH=20 align=center>#</td><td FIXWIDTH=100 align=center>Name</td><td FIXWIDTH=100 align=center>Alliance</td><td FIXWIDTH=100 align=center>Leader</td><td FIXWIDTH=70 align=center>Level</td><td FIXWIDTH=80 align=center>Castle</td><td FIXWIDTH=70 align=center>State</td></tr>");
		_header.append("</table>");
		
		L2Clan[] clanes = ClanTable.getInstance().getClans();
		Arrays.sort(clanes, new ClanCompare<L2Clan>());
		
		// Genero el body
		int i = 0;
		TextBuilder _body = new TextBuilder();
		
		if (clanes.length != 0)
		{
			while ((i < clanes.length) && (i < Config.TOP_CLAN_RESULTS))
			{
				_body.append("<table border=0 cellspacing=0 cellpadding=2 FIXWIDTH=490 bgcolor=" + getColor(i + 1) + ">");
				_body.append("<tr>");
				_body.append("<td FIXWIDTH=20 align=center>" + (i + 1) + "</td>");
				_body.append("<td FIXWIDTH=100 align=center>" + clanes[i].getName() + "</td>");
				String ally = clanes[i].getAllyName() == null ? "" : clanes[i].getAllyName();
				_body.append("<td FIXWIDTH=100 align=center>" + ally + "</td>");
				_body.append("<td FIXWIDTH=100 align=center>" + clanes[i].getLeaderName() + "</td>");
				_body.append("<td FIXWIDTH=70 align=center>" + clanes[i].getLevel() + "</td>");
				String castle = clanes[i].getCastleId() != 0 ? CastleManager.getInstance().getCastleById(clanes[i].getCastleId()).getName() : "";
				_body.append("<td FIXWIDTH=80 align=center>" + castle + "</td>");
				String estado = clanes[i].isAtWar() ? "At War" : "Peace";
				_body.append("<td FIXWIDTH=70 align=center>" + estado + "</td>");
				_body.append("</tr>");
				_body.append("</table>");
				i++;
			}
		}
		
		_topClan = new TopPost(_header.toString(), _body.toString(), "");
		
	}
	
	private void generateTopPk()
	{
		if (!Config.TOP_ALLOW_PKRANK)
		{
			return;
		}
		// Genero el header
		TextBuilder _header = new TextBuilder();
		_header.append("<table border=0 cellspacing=0 cellpadding=2 FIXWIDTH=550 bgcolor=D2D2D2>");
		_header.append("<tr><td FIXWIDTH=50 align=center>#</td><td FIXWIDTH=200 align=center>Name</td><td FIXWIDTH=100 align=center>Class</td><td FIXWIDTH=200 align=center>PK</td></tr>");
		_header.append("</table>");
		
		// Genero el body
		TextBuilder _body = new TextBuilder();
		
		try (Connection con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement statement = con.prepareStatement("SELECT char_name name, pkkills val, base_class base FROM characters WHERE accesslevel = 0 and pkkills > 0  ORDER BY pkkills DESC LIMIT " + Config.TOP_PLAYER_RESULTS))
		{
			int position = 1;
			try (ResultSet result = statement.executeQuery())
			{
				while (result.next())
				{
					_body.append("<table border=0 cellspacing=0 cellpadding=2 FIXWIDTH=550 bgcolor=" + getColor(position) + ">");
					_body.append("<tr>");
					_body.append("<td FIXWIDTH=50 align=center>" + position + "</td>");
					_body.append("<td FIXWIDTH=200 align=center>" + result.getString("name") + "</td>");
					_body.append("<td FIXWIDTH=100 align=center>" + getClassName(result.getInt("base")) + "</td>");
					_body.append("<td FIXWIDTH=200 align=center>" + result.getInt("val") + "</td>");
					_body.append("</tr></table>");
					position++;
				}
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		_topPk = new TopPost(_header.toString(), _body.toString(), "");
	}
	
	private void generateInfoIndex()
	{
		TextBuilder tb = new TextBuilder();
		
		if (!Config.TOP_ALLOW_CASTLEINFO && !Config.TOP_ALLOW_RAIDINFO && !Config.TOP_ALLOW_GRANDBOSSINFO && !Config.TOP_ALLOW_HEROINFO)
		{
			tb.append("");
		}
		else
		{
			tb.append("<br>");
			tb.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=755>");
			tb.append("<tr>");
			tb.append("<td FIXWIDTH=755 align=center valign=top><font name=hs12>LINEAGE II</font></td>");
			tb.append("</tr>");
			tb.append("</table>");
			tb.append("<br>");
			tb.append("<br>");
			tb.append("<table border=0 cellspacing=0 cellpadding=2 FIXWIDTH=755 bgcolor=111111 height=40>");
			tb.append("<tr>");
			tb.append("<td FIXWIDTH=100 align=right><img src=L2UI.bbs_folder WIDTH=32 height=32></td>");
			tb.append("<td FIXWIDTH=480 align=left><font color=E95600>Information</font><br1><font color=AAAAAA>status of heroes, RaidBoss, Castle y GrandBoss.</font></td>");
			tb.append("<td FIXWIDTH=160 align=center><button value=\"\" action=\"bypass _bbshome\" back=L2UI_CT1.MiniMap_DF_MinusBtn_Red fore=L2UI_CT1.MiniMap_DF_MinusBtn_Red WIDTH=32 height=32/></td>");
			tb.append("</tr>");
			tb.append("</table>");
			tb.append("<br>");
			tb.append("<table border=0 cellspacing=0 cellpadding=2 height=50>");
			tb.append("<tr>");
			if (Config.TOP_ALLOW_CASTLEINFO)
			{
				tb.append("<td><button action=\"bypass _bbshome;infoindex;Castle\" value=\"Castle\" WIDTH=100 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
			}
			if (Config.TOP_ALLOW_RAIDINFO)
			{
				tb.append("<td><button action=\"bypass _bbshome;infoindex;Raid\" value=\"Raid Boss\" WIDTH=100 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
			}
			if (Config.TOP_ALLOW_GRANDBOSSINFO)
			{
				tb.append("<td><button action=\"bypass _bbshome;infoindex;Grand\" value=\"Grand Boss\" WIDTH=100 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
			}
			if (Config.TOP_ALLOW_HEROINFO)
			{
				tb.append("<td><button action=\"bypass _bbshome;infoindex;Hero\" value=\"Heroes\" WIDTH=100 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
			}
			tb.append("</tr>");
			tb.append("</table>");
		}
		
		_boardsMenu.put("infoindex", new TopPost(tb.toString(), "", ""));
	}
	
	private void generateTopIndex()
	{
		TextBuilder tb = new TextBuilder();
		
		if (!Config.TOP_ALLOW_PVPRANK && !Config.TOP_ALLOW_PKRANK && !Config.TOP_ALLOW_ADENARANK && !Config.TOP_ALLOW_CLANRANK)
		{
			tb.append("");
		}
		else
		{
			tb.append("<br>");
			tb.append("<table border=0 cellspacing=0 cellpadding=0 WIDTH=755>");
			tb.append("<tr>");
			tb.append("<td FIXWIDTH=755 align=center valign=top><font name=hs12>LINEAGE II</font></td>");
			tb.append("</tr>");
			tb.append("</table>");
			tb.append("<br>");
			tb.append("<br>");
			
			tb.append("<table border=0 cellspacing=0 cellpadding=2 FIXWIDTH=755 bgcolor=111111 height=40>");
			tb.append("<tr>");
			tb.append("<td FIXWIDTH=100 align=right><img src=L2UI.bbs_folder WIDTH=32 height=32></td>");
			tb.append("<td FIXWIDTH=480 align=left><font color=AAAAAA>Ranking</font><br1><font color=AAAAAA>Server statistics.</font></td>");
			tb.append("<td FIXWIDTH=160 align=center><button value=\"\" action=\"bypass _bbshome\" back=L2UI_CT1.MiniMap_DF_MinusBtn_Red fore=L2UI_CT1.MiniMap_DF_MinusBtn_Red WIDTH=32 height=32/></td>");
			tb.append("</tr>");
			tb.append("</table>");
			tb.append("<br>");
			tb.append("<table border=0 cellspacing=0 cellpadding=2 height=50>");
			tb.append("<tr>");
			if (Config.TOP_ALLOW_PVPRANK)
			{
				tb.append("<td><button action=\"bypass _bbshome;topindex;PVP\" value=\"Top PVP\" WIDTH=100 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
			}
			if (Config.TOP_ALLOW_PKRANK)
			{
				tb.append("<td><button action=\"bypass _bbshome;topindex;PK\" value=\"Top PK\" WIDTH=100 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
			}
			if (Config.TOP_ALLOW_ADENARANK)
			{
				tb.append("<td><button action=\"bypass _bbshome;topindex;Adena\" value=\"Top Adena\" WIDTH=100 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
			}
			if (Config.TOP_ALLOW_CLANRANK)
			{
				tb.append("<td><button action=\"bypass _bbshome;topindex;Clan\" value=\"Top Clan\" WIDTH=100 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
			}
			tb.append("</tr>");
			tb.append("</table>");
		}
		_boardsMenu.put("topindex", new TopPost(tb.toString(), "", ""));
	}
	
	private void generateRaidIndex()
	{
		TextBuilder tb = new TextBuilder();
		tb.append("<table border=0 cellspacing=0 cellpadding=2 height=50>");
		tb.append("<tr>");
		tb.append("<td><button action=\"bypass _bbshome;infoindex;Raid;20\" value=\"20+\" WIDTH=50 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
		tb.append("<td><button action=\"bypass _bbshome;infoindex;Raid;30\" value=\"30+\" WIDTH=50 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
		tb.append("<td><button action=\"bypass _bbshome;infoindex;Raid;40\" value=\"40+\" WIDTH=50 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
		tb.append("<td><button action=\"bypass _bbshome;infoindex;Raid;50\" value=\"50+\" WIDTH=50 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
		tb.append("<td><button action=\"bypass _bbshome;infoindex;Raid;60\" value=\"60+\" WIDTH=50 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
		tb.append("<td><button action=\"bypass _bbshome;infoindex;Raid;70\" value=\"70+\" WIDTH=50 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
		tb.append("<td><button action=\"bypass _bbshome;infoindex;Raid;80\" value=\"80+\" WIDTH=50 height=30 back=L2UI_CT1.Tab_DF_Tab_Selected fore=L2UI_CT1.Tab_DF_Tab_Unselected></td>");
		tb.append("</tr>");
		tb.append("</table>");
		_boardsMenu.put("raid_level", new TopPost(tb.toString(), "", ""));
	}
	
	public HomeBBSManager()
	{
		createClassList();
	}
	
	public void startBoard()
	{
		generateBoard();
		ThreadPoolManager.getInstance().scheduleGeneral(new UpdateCommunity(), Config.TOP_LOAD_TIMER * 60 * 1000);
	}
	
	public void generateBoard()
	{
		generateGrandBossList();
		if (olympiad_cycle != Olympiad.getInstance().getCurrentCycle())
		{
			olympiad_cycle = Olympiad.getInstance().getCurrentCycle();
			_heroList.clear();
			generateHeroPage();
		}
		_raidList.clear();
		_boardsMenu.clear();
		generateRaidIndex();
		generateRaidList();
		generateCastlePage();
		generateTopPvp();
		generateTopPk();
		generateTopAdena();
		generateTopClan();
		generateTopIndex();
		generateInfoIndex();
		// by fissban
		generateInfoNews();
		generateInfoGralIndex();
		generateRate();
		generateOtherConfig();
		generateInfoRules();
	}
	
	private TopPost getInfo()
	{
		return _infoGral;
	}
	
	private TopPost getInfoRate()
	{
		return _infoRate;
	}
	
	private TopPost getInfoOther()
	{
		return _infoOther;
	}
	
	private TopPost getInfoNew()
	{
		return _infoNews;
	}
	
	private TopPost getInfoRules()
	{
		return _infoRules;
	}
	
	private TopPost getHero(int index)
	{
		return _heroList.get(index);
	}
	
	private TopPost getRaid(int index, int page)
	{
		return _raidList.get(index).get(page);
	}
	
	private TopPost getGrandBoss()
	{
		return _grandBoss;
	}
	
	private TopPost getPvpRank()
	{
		return _topPvp;
	}
	
	private TopPost getPkRank()
	{
		return _topPk;
	}
	
	private TopPost getAdenaRank()
	{
		return _topAdena;
	}
	
	private TopPost getClanRank()
	{
		return _topClan;
	}
	
	private TopPost getCastle()
	{
		return _castle;
	}
	
	private String getBoardHeader(String b)
	{
		return _boardsMenu.get(b).getHeader();
	}
	
	private void createClassList()
	{
		classList = new HashMap<>();
		classList.put(0, "Fighter");
		classList.put(1, "Warrior");
		classList.put(2, "Gladiator");
		classList.put(3, "Warlord");
		classList.put(4, "Knight");
		classList.put(5, "Paladin");
		classList.put(6, "Dark Avenger");
		classList.put(7, "Rogue");
		classList.put(8, "Treasure Hunter");
		classList.put(9, "Hawkeye");
		classList.put(10, "Mage");
		classList.put(11, "Wizard");
		classList.put(12, "Sorcerer");
		classList.put(13, "Necromancer");
		classList.put(14, "Warlock");
		classList.put(15, "Cleric");
		classList.put(16, "Bishop");
		classList.put(17, "Prophet");
		classList.put(18, "Elven Fighter");
		classList.put(19, "Elven Knight");
		classList.put(20, "Temple Knight");
		classList.put(21, "Swordsinger");
		classList.put(22, "Elven Scout");
		classList.put(23, "Plains Walker");
		classList.put(24, "Silver Ranger");
		classList.put(25, "Elven Mage");
		classList.put(26, "Elven Wizard");
		classList.put(27, "Spellsinger");
		classList.put(28, "Elemental Summoner");
		classList.put(29, "Oracle");
		classList.put(30, "Elder");
		classList.put(31, "Dark Fighter");
		classList.put(32, "Palus Knightr");
		classList.put(33, "Shillien Knight");
		classList.put(34, "Bladedancer");
		classList.put(35, "Assasin");
		classList.put(36, "Abyss Walker");
		classList.put(37, "Phantom Ranger");
		classList.put(38, "Dark Mage");
		classList.put(39, "Dark Wizard");
		classList.put(40, "Spellhowler");
		classList.put(41, "Phantom Summoner");
		classList.put(42, "Shillien Oracle");
		classList.put(43, "Shilien Elder");
		classList.put(44, "Orc Fighter");
		classList.put(45, "Orc Raider");
		classList.put(46, "Destroyer");
		classList.put(47, "Orc Monk");
		classList.put(48, "Tyrant");
		classList.put(49, "Orc Mage");
		classList.put(50, "Orc Shaman");
		classList.put(51, "Overlord");
		classList.put(52, "Warcryer");
		classList.put(53, "Dwarven Fighter");
		classList.put(54, "Scavenger");
		classList.put(55, "Bounty Hunter");
		classList.put(56, "Artisan");
		classList.put(57, "Warsmith");
		classList.put(88, "Duelist");
		classList.put(89, "Dreadnought");
		classList.put(90, "Phoenix Knight");
		classList.put(91, "Hell Knight");
		classList.put(92, "Sagittarius");
		classList.put(93, "Adventurer");
		classList.put(94, "Archmage");
		classList.put(95, "Soultaker");
		classList.put(96, "Arcana Lord");
		classList.put(97, "Cardinal");
		classList.put(98, "Hierophant");
		classList.put(99, "Evas Templar");
		classList.put(100, "Sword Muse");
		classList.put(101, "Wind Rider");
		classList.put(102, "Moonlight Sentinel");
		classList.put(103, "Mystic Muse");
		classList.put(104, "Elemental Master");
		classList.put(105, "Evas Saint");
		classList.put(106, "Shillien Templar");
		classList.put(107, "Spectral Dancer");
		classList.put(108, "Ghost Hunter");
		classList.put(109, "Ghost Sentinel");
		classList.put(110, "Storm Screamer");
		classList.put(111, "Spectral Master");
		classList.put(112, "Shillien Saint");
		classList.put(113, "Titan");
		classList.put(114, "Grand Khavatari");
		classList.put(115, "Dominator");
		classList.put(116, "Doomcryer");
		classList.put(117, "Fortune Seeker");
		classList.put(118, "Maestro");
		classList.put(123, "Male Soldier");
		classList.put(124, "Female Soldier");
		classList.put(125, "Trooper");
		classList.put(126, "Warder");
		classList.put(127, "Berserker");
		classList.put(128, "Male Soulbreaker");
		classList.put(129, "Female Soulbreaker");
		classList.put(130, "Arbalester");
		classList.put(131, "Doombringer");
		classList.put(132, "Male Soulhound");
		classList.put(133, "Female Soulhound");
		classList.put(134, "Trickster");
		classList.put(135, "Inspector");
		classList.put(136, "Judicator");
	}
	
	private String getColor(int p)
	{
		if ((p % 2) == 0)
		{
			return "8B4513";
		}
		return "291405";
	}
	
	private String getClassName(int id)
	{
		return classList.get(id);
	}
	
	public class UpdateCommunity implements Runnable
	{
		@Override
		public void run()
		{
			generateBoard();
			ThreadPoolManager.getInstance().scheduleGeneral(this, Config.TOP_LOAD_TIMER * 60000);
		}
	}
	
	public class ClanCompare<T> implements Comparator<T>
	{
		@Override
		public int compare(Object o1, Object o2)
		{
			if ((o1 instanceof L2Clan) && (o2 instanceof L2Clan))
			{
				L2Clan p1 = (L2Clan) o1;
				L2Clan p2 = (L2Clan) o2;
				if (p1.getLevel() > p2.getLevel())
				{
					return 1;
				}
				else if (p1.getLevel() < p2.getLevel())
				{
					return -1;
				}
				else
				{
					if (p1.getReputationScore() > p2.getReputationScore())
					{
						return 1;
					}
					else if (p1.getReputationScore() < p2.getReputationScore())
					{
						return -1;
					}
					else
					{
						return 0;
					}
				}
			}
			return 0;
		}
	}
	
	public static HomeBBSManager getInstance()
	{
		return SingletonHolder._instance;
	}
	
	private static class SingletonHolder
	{
		protected static final HomeBBSManager _instance = new HomeBBSManager();
	}
}